
#include "copyright.h"
#include "synch.h"
#include "system.h"
#include <iostream>

Thread *ticketClerkThreads[5];


Lock *ticketClerkLineLock;
Condition *ticketClerkLineConditionVariables[5];
Condition *ticketClerkConditionVariables[5];
Lock *ticketClerkLocks[5];


/*int ticketClerkLineLock;
int ticketClerkLineConditionVariables[5];
int ticketClerkConditionVariables[5];
int ticketClerkLocks[5];*/

int ticketClerkLineCount[5];
int ticketsBeingSold[5];
int ticketsTotal[5];
int ticketEarnings[5];
enum ClerkStateEnum{available, busy, on_break, no_clerk,go_on_break} ticketClerkState[5];

const int MAX_CLERK = 5;

void TicketClerk(int clerkNumber)
{

	while(true)
	{
		
		ticketClerkLineLock->Acquire();		//Lock the lines
		ticketClerkLocks[clerkNumber]->Acquire();
		
		/*LockAcquire(ticketClerkLineLock);
		LockAcquire(ticketClerkLocks[clerkNumber]);*/
		
		if(ticketClerkState[clerkNumber]==go_on_break)
		{
			
			ticketClerkLineLock->Release();	// Unlock the lines
			
			/*LockRelease(ticketClerkLineLock);*/
			ticketClerkState[clerkNumber]=on_break;
		}
		else if(ticketClerkState[clerkNumber]!=on_break)
		{
			
			if(ticketClerkLineCount[clerkNumber]>0)	//If there is a line
			{
				printf("%s %i has a line length %i and is signaling a customer\n",currentThread->getName(),clerkNumber,ticketClerkLineCount[clerkNumber]);
				
				ticketClerkLineConditionVariables[clerkNumber]->Signal(ticketClerkLineLock);	//Wake up the first person in line
				
				/*CVSignal(ticketClerkLineConditionVariables[clerkNumber],ticketClerkLineLock);*/
				customersServed++;
				ticketClerkLineCount[clerkNumber]--;	//decrease the line size
				ticketClerkState[clerkNumber]=busy;	//make myself busy
				
				ticketClerkLineLock->Release();	// Unlock the lines
				ticketClerkConditionVariables[clerkNumber]->Wait(ticketClerkLocks[clerkNumber]);
				
				/*LockRelease(ticketClerkLineLock);
				CVWait(ticketClerkConditionVariables[clerkNumber],ticketClerkLocks[clerkNumber]);*/
				customersServed--;
			}
			else					//If there isn't a line
			{
				printf("%s %i has no line. I am available for a customer\n",currentThread->getName(),clerkNumber);
				ticketClerkState[clerkNumber]=available;	//Set myself available
				
				ticketClerkLineLock->Release();	// Unlock the lines
				
				/*LockRelease(ticketClerkLineLock);*/
			}
		}

		do{
			if(ticketClerkState[clerkNumber]==on_break)
			{
				printf("%s %i going on break\n",currentThread->getName(),clerkNumber);
				
				ticketClerkConditionVariables[clerkNumber]->Wait(ticketClerkLocks[clerkNumber]);	//Wait for a customer to signal
				
				/*CVWait(ticketClerkConditionVariables[clerkNumber],ticketClerkLocks[clerkNumber]);*/
				printf("Ticket Clerk %i is coming off of break\n",clerkNumber);
				
				ticketClerkLocks[clerkNumber]->Acquire();
				
				/*LockAcquire(ticketClerkLocks[clerkNumber]);*/
			}
			if(ticketClerkState[clerkNumber]==available)
			{
				
				ticketClerkConditionVariables[clerkNumber]->Wait(ticketClerkLocks[clerkNumber]);	//Wait for a customer to signal
				ticketClerkLocks[clerkNumber]->Acquire();	//Lock my data
				
				/*CVWait(ticketClerkConditionVariables[clerkNumber],ticketClerkLocks[clerkNumber]);
				LockAcquire(ticketClerkLocks[clerkNumber]);*/
			}
		}while(ticketClerkState[clerkNumber]==on_break);

		
		ticketClerkLocks[clerkNumber]->Acquire();
		
		/*LockAcquire(ticketClerkLocks[clerkNumber]);*/
		ticketsTotal[clerkNumber]=ticketsBeingSold[clerkNumber]*12;	//Calculate Ticket Cost
		printf("%s %i has an order for %i and the cost is %i\n",currentThread->getName(),clerkNumber,ticketsBeingSold[clerkNumber],ticketsTotal[clerkNumber]);
		
		
		ticketClerkConditionVariables[clerkNumber]->Signal(ticketClerkLocks[clerkNumber]);	//Let the customer know I he has to pay
		ticketClerkConditionVariables[clerkNumber]->Wait(ticketClerkLocks[clerkNumber]);	//Wait for payment
		
		/*CVSignal(ticketClerkConditionVariables[clerkNumber],ticketClerkLocks[clerkNumber]);
		CVWait(ticketClerkConditionVariables[clerkNumber],ticketClerkLocks[clerkNumber]);*/

		
		ticketClerkLocks[clerkNumber]->Acquire();	//Lock My Shared data
		
		/*LockAcquire(ticketClerkLocks[clerkNumber]);*/
		ticketsTotal[clerkNumber]=0;	//Reset my info
		ticketsBeingSold[clerkNumber]=0;
		
		ticketClerkConditionVariables[clerkNumber]->Signal(ticketClerkLocks[clerkNumber]);	//Wake up customer, signifying that I'm giving him his tickets
		
		/*CVSignal(ticketClerkConditionVariables[clerkNumber],ticketClerkLocks[clerkNumber]);*/
	}
}
